package com.uam.core.lk.utils;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.springframework.util.Assert;

public class Sha256 {

    private static final Charset UTF_8 = StandardCharsets.UTF_8;

    /**
     * Generates a hex-encoded SHA256 checksum from the supplied {@code content}.
     *
     * @param content must not be {@literal null} and not empty.
     * @return hex-encoded SHA256 checksum
     */
    public static String toSha256(String content) {

        Assert.hasText(content, "Content must not be empty");

        return toSha256(content, true, true);
    }

    public static String toSha256(String content, boolean lowercase, boolean fillzero) {

        Assert.hasText(content, "Content must not be empty");

        MessageDigest messageDigest = getMessageDigest("SHA-256");
        byte[] digest = messageDigest.digest(content.getBytes(UTF_8));
        return toHexString(digest, lowercase, fillzero);
    }

    /**
     * Get a MessageDigest instance for the given algorithm. Throws an
     * IllegalArgumentException if <i>algorithm</i> is unknown
     *
     * @return MessageDigest instance
     * @throws IllegalArgumentException if NoSuchAlgorithmException is thrown
     */
    private static MessageDigest getMessageDigest(String algorithm)
                                                                    throws IllegalArgumentException {
        try {
            return MessageDigest.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException("No such algorithm [" + algorithm + "]");
        }
    }

    private static String toHexString(byte[] bytes, boolean lowercase, boolean fillzero) {

        StringBuilder sb = new StringBuilder(bytes.length * 2);

        if (lowercase) {
            if (fillzero) {
                for (byte b : bytes) {
                    sb.append(String.format("%02x", b));
                }
            } else {
                for (byte b : bytes) {
                    sb.append(String.format("%x", b));
                }
            }
        } else {
            if (fillzero) {
                for (byte b : bytes) {
                    sb.append(String.format("%02X", b));
                }
            } else {
                for (byte b : bytes) {
                    sb.append(String.format("%X", b));
                }
            }
        }

        return sb.toString();
    }

    private Sha256() {

    }
}
